/*
 * DSBDirect
 * Copyright (C) 2019 Fynn Godau
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * This software is not affiliated with heinekingmedia GmbH, the
 * developer of the DSB platform.
 */

package godau.fynn.dsbdirect.activity.settings;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import androidx.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import godau.fynn.dsbdirect.BuildConfig;
import godau.fynn.dsbdirect.R;
import godau.fynn.dsbdirect.Utility;
import godau.fynn.dsbdirect.activity.AboutLibrariesActivity;
import godau.fynn.dsbdirect.activity.MainActivity;
import godau.fynn.dsbdirect.manager.DownloadManager;
import godau.fynn.dsbdirect.manager.FileManager;
import godau.fynn.dsbdirect.manager.LoginManager;
import godau.fynn.dsbdirect.table.Table;
import humanize.Humanize;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

// Thanks, https://stackoverflow.com/a/12806877

public class MainSettingsActivity extends SettingsActivity {

    private static final int REQUEST_CODE_STYLING = 1;

    public PreferenceFragment getPreferenceFragment() {
        return new PreferenceFragment();
    }

    public static class PreferenceFragment extends SettingsActivity.PreferenceFragment {

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            // Load the preferences from an XML resource
            addPreferencesFromResource(R.xml.preferences);

            // Behave if pictures are involved
            final boolean containsHtml = getActivity().getIntent().getBooleanExtra(EXTRA_CONTAINS_HTML, true);
            final boolean onlyHtml = getActivity().getIntent().getBooleanExtra(EXTRA_HTML_ONLY, true);

            if (!containsHtml) {
                Preference parse = findPreference("parse");
                parse.setEnabled(false);
                ((CheckBoxPreference) parse).setChecked(false);
                parse.setSummary(R.string.settings_view_parse_not_html);

                // Gray out display empty setting as user will definitely see empty notifications
                Preference displayEmpty = findPreference("displayEmpty");
                displayEmpty.setEnabled(false);
                ((CheckBoxPreference) displayEmpty).setChecked(true);
                // Explain why it is not possible
                displayEmpty.setSummary(R.string.settings_view_parse_not_html);
            } else {
                if (sharedPreferences.getBoolean("parse", true)) {
                    // Explain why it makes sense to download automatically
                    findPreference("autoDownload").setSummary(R.string.settings_polling_download_recommended);

                }

                // Gray out merge preference because merging is not possible when images are involved
                if (!onlyHtml) {
                    Preference merge = findPreference("merge");
                    merge.setEnabled(false);
                    ((CheckBoxPreference) merge).setChecked(false);
                    merge.setSummary(R.string.settings_view_parse_not_exclusively_html);
                }
            }

            // Open Style and Colors settings when user taps Style and Colors settings
            findPreference("styling").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
                    Intent intent = new Intent(getActivity(), StyleSettingsActivity.class);
                    intent.putExtra(EXTRA_HTML_ONLY, onlyHtml);
                    getActivity().startActivityForResult(intent, REQUEST_CODE_STYLING);
                    return true;
                }
            });

            // Set temporary filter setting according to Enable filter setting whenever updated
            findPreference("filter").setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
                @Override
                public boolean onPreferenceChange(Preference preference, Object newValue) {
                    MainActivity.filterEnabled = (Boolean) newValue;
                    return true;
                }
            });

            // Display set filters Set Filter button
            final Preference setFilter = findPreference("set_filter");
            final Handler updateSetFilterSummary = new Handler(new Handler.Callback() {
                @Override
                public boolean handleMessage(Message msg) {
                    Set courseSet = sharedPreferences.getStringSet("courses", new HashSet<String>());
                    String[] concat = new String[courseSet.size() + 2];
                    courseSet.toArray(concat);
                    concat[courseSet.size()] = sharedPreferences.getString("number", "") + sharedPreferences.getString("letter", "");
                    concat[courseSet.size() + 1] = sharedPreferences.getString("name", null);
                    setFilter.setSummary(Utility.smartConcatenate(concat, ", "));
                    return false;
                }
            });
            updateSetFilterSummary.sendEmptyMessage(0);

            // Let Set Filter button open the Set Filter popup
            setFilter.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
                    setFilterPopup(getActivity(), updateSetFilterSummary);

                    return false;
                }
            });

            // Let Check for updates now button Check for updates now
            findPreference("updates_check_now").setOnPreferenceClickListener(getOnCheckUpdateNowClickListener());


            // Disable polling if API level is too low
            if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                Preference poll = findPreference("poll");
                ((CheckBoxPreference) poll).setChecked(false);
                poll.setEnabled(false);
                poll.setSummary(R.string.settings_view_polling_api_too_low);
                findPreference("polling_description").setEnabled(false);
            }

            // Manage logins by tappig Manage logins
            findPreference("login_manage").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
                    startActivity(new Intent(getActivity(), LoginSettingsActivity.class));
                    return true;
                }
            });

            // Gray out Delete all files now when no files are available
            final Preference clearCache = findPreference("clear_cache_now");
            final FileManager fileManager = new FileManager(getActivity());
            final int fileCount = fileManager.countFiles();

            if (fileCount <= 0) {
                clearCache.setEnabled(false);
            }

            // Delete all files when Delete all files now is pressed
            clearCache.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
                    // Prompt for confirmation
                    new AlertDialog.Builder(getActivity())
                            .setTitle(R.string.clear_cache_popup_title)
                            .setMessage(getString(R.string.clear_cache_popup_message,
                                    Humanize.pluralize(
                                            getString(R.string.one_file), "{0} " + getString(R.string.files),
                                            "{0} " + getString(R.string.files), fileCount
                                    ),
                                    Humanize.binaryPrefix(fileManager.occupiedStorage())))
                            .setNegativeButton(R.string.cancel, null)
                            .setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    // Delete all files
                                    fileManager.deleteAllFiles();

                                    // There are no more files left (hopefully)
                                    clearCache.setEnabled(false);
                                }
                            })
                            .show();

                    return true;
                }
            });

            // Schedule or cancel notification when Enable notifications is toggled
            findPreference("poll").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        // Utility will check whether polling is enabled and act accordingly
                        u.schedulePolling();
                    }

                    return true;
                }
            });

            // Show version number in About description preference summary
            findPreference("settings_about_description").setSummary(
                    getString(R.string.credits) + "\n" +
                            getString(R.string.settings_about_description_summary, BuildConfig.VERSION_NAME)
            );

            // Let Write the developer an email message button enable the user to Write the developer an email message
            findPreference("settings_about_email").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
                    emailTheDev(getActivity());
                    return false;
                }
            });

            // Request a parser to be developed button should allow users to Request a parser to be developed
            findPreference("settings_about_request_parser").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
                    new AlertDialog.Builder(getActivity())
                            .setTitle(R.string.request_parser_popup_title)
                            .setMessage(R.string.request_parser_popup_message)
                            .setNegativeButton(R.string.dont_request, null)
                            .setPositiveButton(R.string.transfer_now, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {

                                    final ProgressDialog progressDialog = ProgressDialog.show(
                                            getActivity(), null,
                                            getActivity().getString(R.string.request_parser_uploading_message),
                                            true
                                    );

                                    new Thread(new Runnable() {
                                        @Override
                                        public void run() {

                                            try {

                                                DownloadManager downloadManager = new DownloadManager(getActivity());
                                                LoginManager loginManager = new LoginManager(sharedPreferences);

                                                // Download timetable list
                                                Table[] tables = downloadManager.downloadContentInformation(loginManager.getActiveLogin())
                                                        .getTables();

                                                final boolean success = downloadManager.uploadParserRequest(tables[0].getUri());

                                                getActivity().runOnUiThread(new Runnable() {
                                                    @Override
                                                    public void run() {

                                                        progressDialog.dismiss();

                                                        new AlertDialog.Builder(getActivity())
                                                                .setTitle(success ?
                                                                        R.string.request_parser_uploading_successful_title :
                                                                        R.string.request_parser_uploading_failed_title
                                                                )
                                                                .setMessage(success ?
                                                                        R.string.request_parser_uploading_successful_message :
                                                                        R.string.request_parser_uploading_failed_message
                                                                )
                                                                .setPositiveButton(R.string.ok, null)
                                                                .show();
                                                    }
                                                });

                                            } catch (IOException e) {
                                                e.printStackTrace();

                                                getActivity().runOnUiThread(new Runnable() {
                                                    @Override
                                                    public void run() {
                                                        progressDialog.dismiss();

                                                        new AlertDialog.Builder(getActivity())
                                                                .setTitle(R.string.network_generic_error)
                                                                .setMessage(R.string.network_generic_error_request)
                                                                .setPositiveButton(R.string.ok, null)
                                                                .show();
                                                    }
                                                });
                                            }
                                        }
                                    }).start();


                                }
                            })
                            .show();

                    return true;
                }
            });

            // Manage shortcodes when choosing to Manage shortcodes
            findPreference("shortcode_manage").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
                    startActivity(new Intent(getActivity(), ShortcodeSettingsActivtiy.class));
                    return false;
                }
            });

            // Check out repository when Check out repository is selected
            findPreference("settings_about_repository").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
                    Intent checkOutRepo = new Intent(Intent.ACTION_VIEW);
                    checkOutRepo.setData(Uri.parse(getString(R.string.uri_repository)));
                    startActivity(checkOutRepo);
                    return true;
                }
            });

            // Lead user to page where they can File an issue once they click File an issue
            findPreference("settings_about_issue").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
                    Intent fileAnIssue = new Intent(Intent.ACTION_VIEW);
                    fileAnIssue.setData(Uri.parse(getString(R.string.uri_issue_tracker)));
                    startActivity(fileAnIssue);
                    return true;
                }
            });

            // Show information About libraries upon touching About libraries
            findPreference("settings_about_libraries").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {

                    startActivity(new Intent(getActivity(), AboutLibrariesActivity.class));

                    return true;
                }
            });
        }

        private Preference.OnPreferenceClickListener getOnCheckUpdateNowClickListener() {
            return new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
                    new Utility(getActivity()).checkForUpdate(true, new DownloadManager(getActivity()));
                    return true;
                }
            };
        }

        private String makeTime(int hour, int minute) {
            String minuteString = String.valueOf(minute);
            String hourString = String.valueOf(hour);

            if (minuteString.length() < 2) {
                minuteString = "0" + minuteString;
            }

            if (hourString.length() < 2) {
                hourString = "0" + hourString;
            }
            return hourString + ":" + minuteString;
        }


    }

    public static void setFilterPopup(Context context, @Nullable final Handler ok) {

        // spawn layout
        View promptView = LayoutInflater.from(context).inflate(R.layout.action_filter, null);

        // get sharedPreferences
        final SharedPreferences sharedPreferences1 = new Utility(context).getSharedPreferences();

        // find fields
        final EditText inputNumber = promptView.findViewById(R.id.input_number);
        final EditText inputLetter = promptView.findViewById(R.id.input_letter);
        final EditText inputCourses = promptView.findViewById(R.id.input_courses);
        final EditText inputName = promptView.findViewById(R.id.input_name);

        // fill in data from sharedPreferences

        Set<String> courseSet = sharedPreferences1.getStringSet("courses", new HashSet<String>());
        String[] courseArray = courseSet.toArray(new String[courseSet.size()]);
        String courseString = Utility.smartConcatenate(courseArray, " ");

        inputNumber.setText(sharedPreferences1.getString("number", ""));
        inputLetter.setText(sharedPreferences1.getString("letter", ""));
        inputCourses.setText(courseString);
        inputName.setText(sharedPreferences1.getString("name", ""));

        new AlertDialog.Builder(context)
                .setView(promptView)
                .setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                        String[] courses = inputCourses.getText().toString().split(" ");


                        String number = inputNumber.getText().toString();
                        String letter = inputLetter.getText().toString();
                        String name = inputName.getText().toString();
                        sharedPreferences1.edit()
                                .putString("number", number)
                                .putString("letter", letter)
                                .putStringSet("courses", new HashSet<String>(Arrays.asList(courses)))
                                .putString("name", name)
                                .apply();

                        if (ok != null) {
                            ok.sendEmptyMessage(0);
                        }


                    }
                })
                .setNegativeButton(R.string.cancel, null)
                .setCancelable(false) // user might accidentally click it away otherwise
                .setTitle(R.string.action_filter_popup_title)
                .setMessage(R.string.action_filter_popup_message)
                .show();


    }

    public static void emailTheDev(Context context) {
        Intent emailTheDev = new Intent(Intent.ACTION_VIEW);
        emailTheDev.setData(Uri.parse(context.getString(R.string.email_uri, context.getString(R.string.email_body))));

        context.startActivity(emailTheDev);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        recreate();
    }
}